using Microsoft.Extensions.Options;
using RAG.Application.Dtos.Chat;
using RAG.Application.Services.Interfaces;
using RAG.Domain.Configuration;
using RAG.Domain.Repositories;
using RAG.Domain.Services;
using RAG.Domain.Entities.App;
using System.Diagnostics;
using System.Text.Json;

namespace RAG.Application.Services.Implementations;

public class RagChatService : IRagChatService
{
    private readonly IEmbeddingService _embeddingService;
    private readonly IVectorSearchService _vectorSearchService;
    private readonly IDocumentChunkRepository _chunkRepository;
    private readonly IChatService _chatService;
    private readonly IConversationService _conversationService;
    private readonly ISessionService _sessionService;
    private readonly RAGSettings _ragSettings;

    public RagChatService(
        IEmbeddingService embeddingService,
        IVectorSearchService vectorSearchService,
        IDocumentChunkRepository chunkRepository,
        IChatService chatService,
        IConversationService conversationService,
        ISessionService sessionService,
        IOptions<RAGSettings> ragSettings)
    {
        _embeddingService = embeddingService;
        _vectorSearchService = vectorSearchService;
        _chunkRepository = chunkRepository;
        _chatService = chatService;
        _conversationService = conversationService;
        _sessionService = sessionService;
        _ragSettings = ragSettings.Value;
    }

    public async Task<ChatResponseDto> ChatAsync(ChatRequestDto request, Guid userId)
    {
        var stopwatch = Stopwatch.StartNew();
        
        // 1. 生成问题的向量表示
        var questionEmbedding = await _embeddingService.GenerateTextEmbeddingAsync(request.Question);

        // 2. 在知识库中搜索相似内容
        var similarChunks = await _vectorSearchService.SearchSimilarChunksAsync(
            questionEmbedding,
            _ragSettings.TopK,
            _ragSettings.SimilarityThreshold);

        // 3. 获取相关文档块的详细信息
        var chunkIds = similarChunks.Select(c => c.ChunkId).ToList();
        var chunks = await _chunkRepository.GetChunksWithVectorsAsync(chunkIds);

        // 4. 构建上下文
        var context = BuildContext(chunks, similarChunks);
        var relevantChunks = BuildRelevantChunks(chunks, similarChunks);

        // 5. 生成回答
        var answer = await _chatService.GenerateResponseAsync(
            request.Question,
            context,
            GetChatHistory(request));

        stopwatch.Stop();

        // 6. 获取或创建会话
        var sessionId = await _sessionService.GetOrCreateSessionAsync(request.SessionId, userId, "聊天会话");
        
        // 7. 保存对话记录到数据库
        var sourceDocuments = relevantChunks.Any() ? JsonSerializer.Serialize(relevantChunks) : null;
        
        var conversation = new Conversations
        {
            Id = Guid.NewGuid(),
            Question = request.Question,
            Answer = answer,
            SourceDocuments = sourceDocuments,
            ConfidenceScore = relevantChunks.Any() ? (decimal)relevantChunks.Max(c => c.Similarity) : null,
            ResponseTimeMs = (int)stopwatch.ElapsedMilliseconds,
            UserId = userId,
            SessionId = sessionId,
            CreatedAt = DateTime.UtcNow,
            UpdatedAt = DateTime.UtcNow,
            CreatedBy = userId,
            UpdatedBy = userId
        };

        try
        {
            await _conversationService.SaveConversationAsync(conversation);
        }
        catch (Exception ex)
        {
            // 记录错误但不影响主要功能
            Console.WriteLine($"保存对话记录失败: {ex.Message}");
        }

        // 7. 返回结果
        return new ChatResponseDto
        {
            Answer = answer,
            SessionId = sessionId,
            RelevantChunks = relevantChunks,
            Timestamp = DateTime.UtcNow
        };
    }

    private string BuildContext(
        List<RAG.Domain.Entities.App.DocumentChunks> chunks,
        List<(Guid ChunkId, double Similarity)> similarities)
    {
        var contextBuilder = new System.Text.StringBuilder();

        // 按相似度排序并构建上下文
        var orderedChunks = chunks
            .Join(similarities,
                  c => c.Id,
                  s => s.ChunkId,
                  (chunk, sim) => new { Chunk = chunk, Similarity = sim.Similarity })
            .OrderByDescending(x => x.Similarity)
            .ToList();

        foreach (var item in orderedChunks)
        {
            contextBuilder.AppendLine($"文档: {item.Chunk.Document.Title}");
            contextBuilder.AppendLine($"内容: {item.Chunk.Content}");
            contextBuilder.AppendLine($"相似度: {item.Similarity:F3}");
            contextBuilder.AppendLine("---");
        }

        return contextBuilder.ToString();
    }

    private List<RelevantChunkDto> BuildRelevantChunks(
        List<RAG.Domain.Entities.App.DocumentChunks> chunks,
        List<(Guid ChunkId, double Similarity)> similarities)
    {
        return chunks
            .Join(similarities,
                  c => c.Id,
                  s => s.ChunkId,
                  (chunk, sim) => new RelevantChunkDto
                  {
                      Content = chunk.Content.Length > 200
                          ? chunk.Content.Substring(0, 200) + "..."
                          : chunk.Content,
                      DocumentTitle = chunk.Document.Title,
                      Similarity = sim.Similarity,
                      ChunkIndex = chunk.ChunkIndex
                  })
            .OrderByDescending(x => x.Similarity)
            .ToList();
    }

    private List<string>? GetChatHistory(ChatRequestDto request)
    {
        // TODO: 实现会话历史获取逻辑
        // 可以从数据库中根据SessionId获取历史对话
        return null;
    }
}
